package com.iretailer.report.quartz.horizon.wsSubscribe;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iretailer.report.init.annotation.BootLoading;
import com.iretailer.report.model.Categories;
import com.iretailer.report.model.Device;
import com.iretailer.report.model.GenderAge;
import com.iretailer.report.quartz.horizon.Settings;
import com.iretailer.report.quartz.horizon.common.ClientHttpMethod;
import com.iretailer.report.quartz.horizon.common.Signer;
import com.iretailer.report.quartz.horizon.model.BasicResponseBody;
import com.iretailer.report.quartz.horizon.model.VistorsModel;
import com.iretailer.report.service.CategoriesService;
import com.iretailer.report.service.DevicesService;
import com.iretailer.report.service.FaceService;
import com.iretailer.report.util.SpringUtils;
import com.iretailer.report.util.StringUtil;
import com.iretailer.report.util.TimeUtil;
import org.java_websocket.client.WebSocketClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @Auther: xjw
 * @Date: 2019/10/17 0017 13:27
 * @Description:
 */
public class SubscribeImp implements Subscribe {

    private final static Logger log = LoggerFactory.getLogger(Subscribe.class);

    private FaceService faceService = (FaceService) SpringUtils.getBean("faceService");
    private CategoriesService categoriesService = (CategoriesService) SpringUtils.getBean("categoriesService");
    private DevicesService devicesService = (DevicesService) SpringUtils.getBean("devicesService");

    private Signer signer;
    private String topicName;
    private String topicId;
    private String subscriptionId;
    private String clientId;
    private String passHost;
    private String wsHost;
    private boolean status = true;
    private SortedMap<String, String> wsHeaders;
    private URI wsURI;

    public SubscribeImp(Signer signer, String passHost, String wsHost, String topicName, String topicId) {
        this.signer = signer;
        this.topicName = topicName;
        this.topicId = topicId;
        this.passHost = passHost;
        this.wsHost = wsHost;
        this.clientId = TimeUtil.localDateTime_format(LocalDateTime.now(), "yyyyMMddHHmmssSSS");
    }

    @Override
    public String getClientId() {
        return clientId;
    }

    @Override
    public SortedMap<String, String> getWsHeaders() {
        return wsHeaders;
    }

    @Override
    public URI getWsURI() {
        return wsURI;
    }

    @Override
    public boolean getStatus() {
        return status;
    }

    public void setStatus(boolean status) {
        this.status = status;
    }

    public WebSocketClient getWebSocketClient() {
        boolean sub = subVisitors();
        if (sub) {
            this.wsHeaders = new TreeMap<>();
            this.wsHeaders.put("host", this.wsHost);
            String authorization = null;
            try {
                authorization = this.signer.Sign(HttpMethod.GET, "/ws", new TreeMap<>(), this.wsHeaders);
                this.wsHeaders.put("hobot_xpush_client_id", clientId);
                String APIURL = String.format("ws://%s/ws", wsHost);
                this.wsURI = URI.create(String.format("%s?authorization=%s", APIURL, authorization));
                HorizonWsClient client = new HorizonWsClient(this);
                return client;
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    /**
     * 发起订阅
     */
    @Override
    public boolean subVisitors() {
//        String SubVisitorsURL = "/openapi/v1/analysis_tools/visitors/sub";
//        SortedMap<String, String> subHeaders = new TreeMap<String, String>();
//        SortedMap<String, String> subParams = new TreeMap<String, String>();
//        subHeaders.put("content-type", "application/json");
//        subHeaders.put("host", this.passHost);
////        String body = "{\"topic_name\":\"device\",\"topic_id\":\"0694E001020110625L\",\"client_id\":\"" + clientId + "\"}";
//        JSONObject body = new JSONObject();
//        body.put("topic_name", this.topicName);
//        body.put("topic_id", this.topicId);
//        body.put("client_id", this.clientId);
//        ResponseEntity<BasicResponseBody> result = null;
//        try {
//            result = ClientHttpMethod.getHttpMethod(this.signer).httpPUT(BasicResponseBody.class, SubVisitorsURL, subHeaders, subParams, JSON.toJSONString(body));
//            if (result.getStatusCode() == HttpStatus.OK) {
//                BasicResponseBody res = result.getBody();
//                if (res.getMessage().equals("success")) {
//                    this.subscriptionId = res.getData().getString("subscription_id");
//                    return true;
//                } else {
//                    log.error("subscribe is fasle  msg: {}", JSON.toJSONString(result.getBody()));
//                }
//            } else {
//                log.error("subscribe is error {}", result.getStatusCodeValue());
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//        }
        return false;
    }


    @Override
    public boolean processMessage(String msg) {
        log.error(msg);
        VistorsModel vm = JSON.parseObject(msg, VistorsModel.class);
        if (vm != null && StringUtil.notEmpty(vm.getDeviceSn())) {
            // 进店
            if (vm.getInOutType() == 0) {
                Device device = devicesService.selectDeviceBySN(vm.getDeviceSn());
                if (device != null) {
                    Map<String, Categories> ageTypeMap = categoriesService.getAgeTypeMap();
                    GenderAge genderAge = new GenderAge();
                    Categories ageType = ageTypeMap.get(String.valueOf(vm.getAge()));
                    if (ageType != null) {
                        genderAge.setAgeType(ageType.getData());
                    } else {
                        genderAge.setAgeType("");
                    }
                    genderAge.setGender(vm.getGender());
                    LocalDateTime dateTime = LocalDateTime.ofEpochSecond(vm.getEventTime() / 1000, 0, OffsetDateTime.now().getOffset());
                    genderAge.setDate(dateTime.toLocalDate());
                    genderAge.setDateTime(dateTime);
                    genderAge.setDid(device.getId());
                    genderAge.setPersonId(vm.getFaceId());
                    genderAge.setImageUrl(vm.getCaptureUrl().getUrl());

                    log.error("---------subscribe face -------- {}", dateTime);
//                    faceService.insertGenderAge(genderAge);

                    return true;
                } else {
                    log.error("horizon face sn not find {}", vm.getDeviceSn());
                }
            }
        } else {
            log.error("---- horizon {}", JSON.toJSONString(vm));
        }
        return false;
    }

    public boolean cancelSub() {
        if (StringUtil.notEmpty(subscriptionId)) {
            String APIURL = String.format("/openapi/v1/analysis_tools/visitors/sub/%s", subscriptionId);
            SortedMap<String, String> headers = new TreeMap<String, String>();
            SortedMap<String, String> params = new TreeMap<String, String>();
            headers.put("host", Settings.PAAS_HOST);
            ResponseEntity<BasicResponseBody> result = null;
            try {
                result = ClientHttpMethod.getHttpMethod(signer).httpDelete(BasicResponseBody.class, APIURL, headers, params);
                if (result.getStatusCode() == HttpStatus.OK) {
                    BasicResponseBody res = result.getBody();
                    if (res.getMessage().equals("succcess")) {
                        log.error("cancel is success");
                        return true;
                    } else {
                        log.error("cancel is fasle {}", JSON.toJSONString(result.getBody()));
                    }
                } else {
                    log.error("cancel is error {}", result.getStatusCodeValue());
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        } else {
            log.error("cancel is false subscription id is empty");
        }
        return false;
    }

}
